package cn.cloudtogo.server.module.datasource;

import cn.cloudtogo.common.Assert;
import cn.cloudtogo.common.model.ExternalDatasourceDao;
import cn.cloudtogo.common.model.ExternalDatasourceModel;
import cn.cloudtogo.common.model.ExternalDatasourceRowMapper;
import cn.cloudtogo.common.util.StringHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.cloudtogo.common.GendbGlobalConstant.SCHEMA_SYSTEM;
import static cn.cloudtogo.common.GendbGlobalConstant.TABLE_EXTERNAL_DATASOURCE;

/**
 * @author yaolianhua789@gmail.com
 **/
@Service
@Slf4j
public class GendbExternalDatasourceDao implements ExternalDatasourceDao {

    private final JdbcTemplate jdbcTemplate;

    public GendbExternalDatasourceDao(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public ExternalDatasourceModel query(String uuid) {

        String query = String.format("SELECT * FROM %s.%s WHERE _uuid = ? ", SCHEMA_SYSTEM, TABLE_EXTERNAL_DATASOURCE);
        try {
            ExternalDatasourceModel externalDatasourceModel = jdbcTemplate.queryForObject(query, new ExternalDatasourceRowMapper(), uuid);
            return externalDatasourceModel;
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    @Override
    public List<ExternalDatasourceModel> list() {
        String sql = String.format("select * from %s.%s", SCHEMA_SYSTEM, TABLE_EXTERNAL_DATASOURCE);
        List<ExternalDatasourceModel> datasources = jdbcTemplate.query(sql, new ExternalDatasourceRowMapper());
        return datasources;
    }

    @Override
    public List<ExternalDatasourceModel> list(String openid) {
        String sql = String.format("select * from %s.%s where openid = ?", SCHEMA_SYSTEM, TABLE_EXTERNAL_DATASOURCE);
        List<ExternalDatasourceModel> datasources = jdbcTemplate.query(sql, new ExternalDatasourceRowMapper(), openid);
        return datasources;
    }

    @Override
    public void delete(String uuid) {
        String deleteSql = String.format("DELETE FROM %s.%s WHERE _uuid = ? ", SCHEMA_SYSTEM, TABLE_EXTERNAL_DATASOURCE);
        int deleted = jdbcTemplate.update(deleteSql, uuid);
        log.info("delete external datasource record success {}", deleted);
    }

    @Override
    public void save(ExternalDatasourceModel externalDatasourceModel) {

        Map<String, Object> param = new HashMap<>(32);
        param.put("_uuid", externalDatasourceModel.getUuid());
        param.put("host", externalDatasourceModel.getHost());
        param.put("port", externalDatasourceModel.getPort());
        param.put("username", externalDatasourceModel.getUsername());
        param.put("password", externalDatasourceModel.getPassword());
        param.put("url", externalDatasourceModel.getUrl());
        param.put("project", externalDatasourceModel.getProject());
        param.put("_schema", externalDatasourceModel.getSchema());
        param.put("name", externalDatasourceModel.getName());
        param.put("openid", externalDatasourceModel.getOpenid());
        param.put("type", externalDatasourceModel.getType());
        param.put("created_at", LocalDateTime.now());

        int execute = new SimpleJdbcInsert(jdbcTemplate)
                .withTableName(String.format("%s.%s", SCHEMA_SYSTEM, TABLE_EXTERNAL_DATASOURCE))
                .execute(param);
        log.info("insert external datasource success {}", execute);
    }

    @Override
    public void updateByUuid(ExternalDatasourceModel externalDatasourceModel) {
        String updateSql = String.format("update %s.%s set openid = ?,project = ?,name = ?,_schema = ?,host = ?,port = ?,username = ?,password = ?,url = ?,type = ?,created_at = ? WHERE _uuid = ? ", SCHEMA_SYSTEM, TABLE_EXTERNAL_DATASOURCE);
        String uuid = externalDatasourceModel.getUuid();
        Assert.notNull(uuid, () -> "uuid is null");
        ExternalDatasourceModel model = this.query(uuid);
        String name = StringHelper.hasTextOrDefault(externalDatasourceModel.getName(), model.getName());
        String project = StringHelper.hasTextOrDefault(externalDatasourceModel.getProject(), model.getProject());
        String host = StringHelper.hasTextOrDefault(externalDatasourceModel.getHost(), model.getHost());
        Integer port = externalDatasourceModel.getPort() == null ? model.getPort() : externalDatasourceModel.getPort();
        String username = StringHelper.hasTextOrDefault(externalDatasourceModel.getUsername(), model.getUsername());
        String password = StringHelper.hasTextOrDefault(externalDatasourceModel.getPassword(), model.getPassword());
        String url = StringHelper.hasTextOrDefault(externalDatasourceModel.getUrl(), model.getUrl());
        LocalDateTime createAt = externalDatasourceModel.getCreateAt() == null ? model.getCreateAt() : externalDatasourceModel.getCreateAt();
        String openid = StringHelper.hasTextOrDefault(externalDatasourceModel.getOpenid(), model.getOpenid());
        String schema = StringHelper.hasTextOrDefault(externalDatasourceModel.getSchema(), model.getSchema());
        String type = StringHelper.hasTextOrDefault(externalDatasourceModel.getType().toString(), model.getType().toString());
        int update = jdbcTemplate.update(updateSql, openid, project, name, schema, host, port, username, password, url, type, createAt, uuid);
        log.info("update external datasource record success {}", update);
    }

    @Override
    public void replaceUuid(String uuid, String objectId) {
        String migrateUuidSql = String.format("update %s.%s set _uuid = ? where _uuid = ?", SCHEMA_SYSTEM, TABLE_EXTERNAL_DATASOURCE);
        jdbcTemplate.update(migrateUuidSql, objectId, uuid);
    }
}
